package Script;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;

/**
 * Stores all special characters for the tablefile.
 * Used to convert between control code and new-lines,
 * as well as scrip-specific code (<END> etc.).
 * 
 * The <END> tag is duplicated, using a stand-alone
 * tag as well as one with a line separator at the end.
 * This is so that scripts without a lb. can be inserted
 * as usual. But the tablefile will always return the one
 * with a libebreak when dumping.
 * 
 * @author Tobias Edin
 *
 */
public class SpecialCharSet {
	private HashMap<TableValueWrapper, String> dumpTable;
	private HashMap<String, TableValueWrapper> insertTable;
	private HashSet<String> startCharacters;
	
	public SpecialCharSet() {
		dumpTable = new HashMap<TableValueWrapper, String>();
		insertTable = new HashMap<String, TableValueWrapper>();
		startCharacters = new HashSet<String>();
		
		/* Add all starting characters. */
		startCharacters.add("*");
		startCharacters.add("/");
	}
	
	/**
	 * Adds a set of special chars to both tables.
	 * 
	 * @param hex Hex value.
	 * @param spChar String to be printed/read from script.
	 * @param start Beginning character in table file (*, / etc.)
	 * @return True if inserted correctly, otherwise false.
	 */
	public boolean addSpecialChar(byte[] hex, char start) {
		String[] spChar = getSpecialChar(start);
		
		
		if (hex != null && spChar != null) {
			for (int i = 0; i < spChar.length; i++) {
				dumpTable.put(new TableValueWrapper(hex), spChar[i]);
				insertTable.put(spChar[i], new TableValueWrapper(hex));
			}
			
			return true;
			
		} else {
			return false;
		}
	}
	
	/**
	 * Gets the script characters connected to a hex value.
	 * If there are multiple entries for the same byte,
	 * only the first is returned.
	 */
	public String get(byte[] hex) {
		return dumpTable.get(new TableValueWrapper(hex));
	}
	
	/**
	 * Returns the hex value connected to a character string.
	 * First extracts the byte data from the TableValueWrapper.
	 */
	public byte[] get(String spChar) {
		TableValueWrapper wrapper = insertTable.get(spChar);
		
		if (wrapper != null) {
			return wrapper.getData();
		} else {
			return null;
		}
	}
	
	/**
	 * Checks if the first character in a tablefile line marks a
	 * special scrip character.
	 */
	public boolean isSpecialCharacter(String c) {
		return startCharacters.contains(c);
	}
	
	/**
	 * Needed to make sure that any special character tab is
	 * always read even when there's no regular table entry
	 * of equal length.
	 * 
	 * @return
	 */
	public int getLongestTextEntry() {
		Collection<String> dumpText = dumpTable.values();
		int longest = 0;
		
		for (String s : dumpText) {
			if (s.length() > longest) {
				longest = s.length();
			}
		}
		
		return longest;
	}
	
	private String[] getSpecialChar(char c) {
		String sep = System.getProperty("line.separator");
		
		switch (c) {
		case '*':
			return new String[]{"<LINE>", ("<LINE>" + sep)};
		case '/':
			return new String[]{ "<END>", ("<END>" + sep)};
		
		default:
			return null;
		}
	}

}
